package com.network.util.ping;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class Ping implements Serializable
{
	private static final long serialVersionUID = 8591788983200399122L;
	private static final String osName = System.getProperty("os.name");

	 static String PING_CMD = "ping -n 1";
	 
	private float maximum = 0;
	private float minimum = 0;
	private float average = 0;
	private int send = 0;
	private int received = 0;
	private float loss = 0;
	private String commet = "";

	public static Ping ping(String remoteHost, int count)
	{
		Ping rtnCode = new Ping();
		String pingCmd = getPingCommand(remoteHost, count);
		if (pingCmd.equals("") == false)
		{
			try
			{
				Process proc = Runtime.getRuntime().exec(pingCmd);
				System.out.println("Please wait...");
				boolean procExit = false;
				Pattern lossRegex = getLostRegex();
				Pattern countRegex = getCountRegex();
				while (procExit == false)
				{
					String strLine = "";
					while ((strLine = readLine(proc.getInputStream())) != null)
					{
						rtnCode.commet = rtnCode.commet + strLine;
						if (strLine.startsWith("Reply from") || strLine.startsWith("Request timed out"))
						{
							continue;
						}
						Matcher match = lossRegex.matcher(strLine);
						if (match.matches())
						{
							rtnCode.send = Integer.valueOf(match.group(1));
							rtnCode.received = Integer.valueOf(match.group(2));
							rtnCode.loss = Float.valueOf(match.group(3));
						}
						match = countRegex.matcher(strLine);
						if (match.matches())
						{
							rtnCode.minimum = Float.valueOf(match.group(1));
							rtnCode.maximum = Float.valueOf(match.group(2));
							rtnCode.average = Float.valueOf(match.group(3));
						}
					}

					try
					{
						proc.exitValue();
						procExit = true;
					}
					catch (IllegalThreadStateException ex)
					{
					}
				}
				proc.destroy();
			}
			catch (IOException ex)
			{
				ex.printStackTrace();
			}
		}
		return rtnCode;
	}

	public static boolean execPing(String s, int count) {
        String s1 = getPingCommand(s,count);
        
        RunCmd runcmd = new RunCmd(s1);
        runcmd.start();
        do {
            try {
                Thread.sleep(100L);
            } catch (Exception _ex) {
            }
        } while (!runcmd.finished);
        if (osName.startsWith("Windows")) {
            if (!runcmd.result || runcmd.exitValue != 0) {
                return false;
            }
            String s2;
            return (s2 = runcmd.stdout.toString()).indexOf("Reply from") != -1 && s2.indexOf("bytes=") != -1;
        }
        if (osName.startsWith("Linux") || osName.startsWith("FreeBSD")) {
            if (!runcmd.result || runcmd.exitValue != 0) {
                return false;
            }
            String s3;
            return (s3 = runcmd.stdout.toString()).indexOf("64 bytes from") != -1;
        }
        return runcmd.result && runcmd.exitValue == 0;
    }
	
	private static String getPingCommand(String remoteHost, int count)
	{
		String command = "";
		 if (osName.startsWith("SunOS") || osName.startsWith("Solaris")) {
            PING_CMD = "/usr/sbin/ping ";
            command = new String(PING_CMD + " " + remoteHost + " " + count);
        } else if (osName.startsWith("Linux")) {
            PING_CMD = "/bin/ping -c 1 -w 1 ";
            command = new String(PING_CMD + " " + remoteHost);
        } else if (osName.startsWith("FreeBSD")) {
            PING_CMD = "/sbin/ping -c 1";
            command = new String(PING_CMD + " " + remoteHost);
        } else if (!osName.startsWith("Windows")) {
            PING_CMD = "ping -n " + count;
            command = new String(PING_CMD + " " + remoteHost);
        } else {
            PING_CMD = "ping -n " + count;
            command = new String(PING_CMD + " " + remoteHost);
        }
		 
//		if (osName.startsWith("Windows"))
//		{
//			command = "ping -n " + count + " " + remoteHost;
//		}
//		else if (osName.equals("SunOS"))
//		{
//			command = "ping -s " + remoteHost + " 56 " + count;
//		}
//		else if (osName.equals("Linux"))
//		{
//			command = "ping -s " + remoteHost;
//		}
		
		
		return command + "\n";
	}

	private static Pattern getLostRegex()
	{
		Pattern rtnCode = null;
		if (osName.startsWith("Windows"))
		{
			rtnCode = Pattern.compile(".*Packets: Sent = ([0-9]+), Received = ([0-9]+), Lost = [0-9]+ [(]([0-9.]+)% loss[)].*[\r\n]*");
		}
		else if (osName.equals("SunOS"))
		{
			//10 packets transmitted, 10 packets received, 0% packet loss
			rtnCode = Pattern.compile(".*([0-9]+) packets transmitted, ([0-9]+) packets received, ([0-9.]+)% packet loss.*[\r\n]*");
		}
		else if (osName.equals("Linux"))
		{
			//6 packets transmitted, 6 packets received, 0% packet loss
			rtnCode = Pattern.compile(".*([0-9]+) packets transmitted, ([0-9]+) packets received, ([0-9.]+)% packet loss.*[\r\n]*");
		}
		return rtnCode;
	}

	private static Pattern getCountRegex()
	{
		Pattern rtnCode = null;
		if (osName.startsWith("Windows"))
		{
			rtnCode = Pattern.compile(".*Minimum = ([0-9.]+)ms, Maximum = ([0-9.]+)ms, Average = ([0-9.]+)ms.*[\r\n]*");
		}
		else if (osName.equals("SunOS"))
		{
			//round-trip (ms)  min/avg/max = 0/0/1
			rtnCode = Pattern.compile(".*round-trip (ms)  min/avg/max = ([0-9]+)/([0-9]+)/([0-9]+).*[\r\n]*");
		}
		else if (osName.equals("Linux"))
		{
			//round-trip (ms)  min/avg/max = 1/1/1
			rtnCode = Pattern.compile(".*round-trip (ms)  min/avg/max = ([0-9]+)/([0-9]+)/([0-9]+).*[\r\n]*");
		}
		return rtnCode;
	}

	private static String readLine(InputStream is) throws IOException
	{
		if (is.available() <= 0)
		{
			return null;
		}
		String strLine = "";
		int chs = 0;
		boolean readStop = false;
		boolean isCrLf = false;
		while (readStop == false)
		{
			chs = is.read();
			switch (chs)
			{
				case -1:
				{
					readStop = true;
					strLine = null;
					break;
				}
				case 10:
				case 13:
				{
					if (strLine.length() > 0)
					{
						strLine = strLine + (char) 10;
						readStop = true;
					}
					break;
				}
				default:
				{
					if (isCrLf == false)
					{
						strLine = strLine + (char) chs;
					}
					break;
				}
			}
		}
		if (strLine != null)
		{
			strLine = strLine.replaceAll("[\r\n]+", "\n");
		}
		return strLine;
	}

	@Override
	public String toString()
	{
		return "Send[" + this.send + "],Received[" + this.received + "],loss[" + this.loss + "%],Maximum[" + this.maximum + "],Minimum[" + this.minimum + "],Average[" + this.average + "]";
	}

	public static void main(String args[])
	{
		Ping ping = Ping.ping(args[0], 10);
		System.out.println(ping);
	}

	public float getAverage()
	{
		return this.average;
	}

	public String getCommet()
	{
		return this.commet;
	}

	public float getLoss()
	{
		return this.loss;
	}

	public float getMaximum()
	{
		return this.maximum;
	}

	public float getMinimum()
	{
		return this.minimum;
	}

	public int getReceived()
	{
		return this.received;
	}

	public int getSend()
	{
		return this.send;
	}

}
